package com.baba.vote.service.impl;


import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.baba.vote.common.VoteException;
import com.baba.vote.config.AliOssConfig;
import com.baba.vote.service.FileService;
import com.baba.vote.util.StringSpitUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;

/**
 * @auther lyd
 * @createDate 2019/8/25 22:06
 */
@Service
@Slf4j
public class FileServiceImpl implements FileService {

  @Autowired
  private AliOssConfig aliOssConfig;

  @Override
  public void downloadFile(String filePath, String newFileName, HttpServletResponse response) {

    File file = new File(filePath);

    if (!file.exists()) {
      log.error("【download file】, 文件不存在, file={}", file.getName());
      throw new VoteException("下载文件不存在(文件没有被创建)");
    }

    // 配置文件下载
    response.setHeader("content-type", "application/octet-stream");
    response.setContentType("application/octet-stream");

    // 下载文件能正常显示中文
    try {
      response.setHeader("Content-Disposition", "attachment;filename="
          + new String((newFileName + StringSpitUtil.cutFileSuffix(filePath)).getBytes(StandardCharsets.UTF_8),
          "ISO8859-1" ));
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    byte[] buffer = new byte[1024];

    FileInputStream fileInputStream = null;

    try {
      int iflag = 0;

      fileInputStream = new FileInputStream(file);

      OutputStream outputStream  = response.getOutputStream();

      while (iflag != -1) {

        iflag = fileInputStream.read(buffer);
        outputStream.write(buffer);
      }

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if ( fileInputStream != null) {
        try {
          fileInputStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  @Override
  public String downloadPicture(String picUrl, String tagDir, String fileName) {

    File file = new File(tagDir);

    if (!file.exists()) {
      file.mkdirs();
    }

    OutputStream out = null;

    URL url = null;

    URLConnection urlConnection = null;

    InputStream in = null;

    byte [] buffer = new byte[2048];

    int len;

    String saveFileDir = null;

    try {

      saveFileDir = tagDir + fileName + ".jpg";

      out = new FileOutputStream(new File(saveFileDir));

      url = new URL(picUrl);

      urlConnection = url.openConnection();

      // 设置超时时间
      urlConnection.setConnectTimeout(5*1000);

      // 获取远程图片的流
      in = urlConnection.getInputStream();

      while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
      }

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (out != null) {
        try {
          out.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }

      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

    return saveFileDir;
  }

  @Override
  public String uploadPictureAliOss(String filePath) {

    // 创建OSSClient实例。
    OSSClient ossClient = new OSSClient(aliOssConfig.getEndpoint(), aliOssConfig.getAccessKey(), aliOssConfig.getSecretKey());

    String objectName = StringSpitUtil.cutFileNameAccordingToPath(filePath);

    // 上传文件
    try {
      ossClient.putObject(aliOssConfig.getBucket(), objectName, new File(filePath));
    } catch (OSSException e) {
      throw new VoteException(e.getErrorCode());
    }

    return aliOssConfig.getOssPrefix() + objectName;
  }

  @Override
  public String uploadPictureAliOss(InputStream fileInputStream, String objectName) {

    // 创建OSSClient实例。
    OSSClient ossClient = new OSSClient(aliOssConfig.getEndpoint(), aliOssConfig.getAccessKey(), aliOssConfig.getSecretKey());

    // 上传文件
    try {
      ossClient.putObject(aliOssConfig.getBucket(), objectName, fileInputStream);
    } catch (OSSException e) {
      throw new VoteException(e.getErrorCode());
    }

    return aliOssConfig.getOssPrefix() + objectName;
  }

  @Override
  public void deletePictureAliOss(String objectNamePath) {
    // 创建OSSClient实例。
    OSSClient ossClient = new OSSClient(aliOssConfig.getEndpoint(), aliOssConfig.getAccessKey(), aliOssConfig.getSecretKey());

    String objectName = StringSpitUtil.cutFileNameAccordingToPath(objectNamePath);

    try {
      ossClient.deleteObject(aliOssConfig.getBucket(), objectName);

    } catch (OSSException e) {
      throw new VoteException(e.getErrorCode());
    }

    ossClient.shutdown();
  }

  @Override
  public String writePic2Disk(InputStream inputStream, String tagDir, String fileName) {

    byte [] buffer = new byte[2048];

    InputStream in = null;

    int len;

    int cumulativeNumber = 0;

    OutputStream out = null;

    String saveFileAbsName = null;

    try {

      in = inputStream;

      File qrcodeFileDir = new File(tagDir);

      if (!qrcodeFileDir.exists()) {
        qrcodeFileDir.mkdirs();
      }

      saveFileAbsName = tagDir + "/" + fileName;

      out = new FileOutputStream(saveFileAbsName);

      while ((len = in.read(buffer)) != -1) {

        out.write(buffer, 0, len);

        cumulativeNumber++;
      }

      if (cumulativeNumber <= 4) {
        return null;
      }

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (out != null) {
        try {
          out.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

    return saveFileAbsName;
  }

  @Override
  public void deleteLocalFile(String filePath) {

    File file = new File(filePath);

    if (file.isDirectory()) {

      File[] files = file.listFiles();

      for (File element : files) {

        if (element.isDirectory()) {

          deleteLocalFile(filePath + "/" + element.getName());

        } else {

          element.delete();
        }
      }

      file.delete();

    } else {
      file.delete();
    }
  }





  /**
   * 根据日期+随机数生成文件名
   * @return
   */
  private String dateGenerationFileName() {

    Random random = new Random();

    int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;

    SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

    return df.format(new Date())+rannum+ ".jpg";
  }


  @Override
  public String upload(MultipartFile file, String path, String newFileName){

//    String fileName = Optional.ofNullable(file.getOriginalFilename())
//        .orElseThrow(() -> new VoteException("上传文件不存在名字"));
//
//    //扩展名
//    //abc.jpg
//    String fileExtensionName = fileName.substring(fileName.lastIndexOf(".")+1);
    String uploadFileName = newFileName + ".jpg";

    File fileDir = new File(path);
    if(!fileDir.exists()){
      fileDir.setWritable(true);
      fileDir.mkdirs();
    }
    File targetFile = new File(path,uploadFileName);
    // 检测是否存在目录
    if (!targetFile.getParentFile().exists()) {
      targetFile.getParentFile().mkdirs();// 新建文件夹
    }

    try {

      writePic2Disk(file.getInputStream(), targetFile.getParentFile().getAbsolutePath(), uploadFileName);

      // 删除文件
//      targetFile.delete();

    } catch (IOException e) {
      log.error("上传文件异常",e);
      return null;
    }

    return targetFile.getAbsolutePath();
  }

}
